<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale-1.0">
    <title>待办事项</title>
    
    <style>
        /* 0. 全局重置和基础样式 */
        :root {
            /* 颜色变量 */
            --color-bg: #111827; /* bg-gray-900 */
            --color-bg-light: #1f2937; /* bg-gray-800 */
            --color-bg-input: #374151; /* bg-gray-700 */
            --color-border: #4b5563; /* border-gray-600 */
            --color-text: #f3f4f6; /* text-gray-100 */
            --color-text-light: #9ca3af; /* text-gray-400 */
            --color-text-dim: #6b7280; /* text-gray-500 */
            --color-blue: #3b82f6; /* bg-blue-600 */
            --color-blue-dark: #2563eb; /* border-blue-700 */
            --color-blue-hover: #2563eb; /* hover:bg-blue-700 */
            --color-red-hover: #ef4444; /* hover:text-red-500 */
            --shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        html {
            color-scheme: dark;
        }

        body {
            /* 基础字体*/
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background-color: var(--color-bg);
            color: var(--color-text);
            /* 布局: flex items-center justify-center min-h-screen p-4 */
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            padding: 1rem; /* p-4 */
        }

        /* 1. 容器和标题 */
        .app-container {
            /* bg-gray-800 shadow-2xl rounded-lg w-full max-w-lg p-4 md:p-6 */
            background-color: var(--color-bg-light);
            box-shadow: var(--shadow);
            border-radius: 0.5rem; /* rounded-lg */
            width: 100%;
            max-width: 32rem; /* max-w-lg */
            padding: 1rem; /* p-4 */
        }

        /* (7) 响应式设计: md:p-6 */
        @media (min-width: 768px) {
            .app-container {
                padding: 1.5rem; /* p-6 */
            }
        }

        .app-title {
            /* text-3xl font-bold text-center text-white mb-6 */
            font-size: 1.875rem; /* text-3xl */
            font-weight: 700; /* font-bold */
            text-align: center;
            color: #ffffff;
            margin-bottom: 1.5rem; /* mb-6 */
        }

        /* 2. 表单和输入 */
        #todo-form {
            /* flex items-center gap-3 mb-4 */
            display: flex;
            align-items: center;
            gap: 0.75rem; /* gap-3 */
            margin-bottom: 1rem; /* mb-4 */
        }

        #todo-input {
            /* flex-grow p-3 bg-gray-700 border-2 border-gray-600 rounded-lg text-white focus:outline-none focus:border-blue-500 transition duration-200 */
            flex-grow: 1;
            padding: 0.75rem; /* p-3 */
            background-color: var(--color-bg-input);
            border: 2px solid var(--color-border);
            border-radius: 0.5rem; /* rounded-lg */
            color: #ffffff;
            transition: border-color 0.2s;
        }

        #todo-input:focus {
            outline: none;
            border-color: var(--color-blue); /* focus:border-blue-500 */
        }

        #todo-form button {
            /* bg-blue-600 text-white p-3 rounded-lg font-semibold hover:bg-blue-700 transition ... */
            background-color: var(--color-blue);
            color: #ffffff;
            padding: 0.75rem; /* p-3 */
            border-radius: 0.5rem; /* rounded-lg */
            font-weight: 600; /* font-semibold */
            border: none;
            cursor: pointer;
            transition: background-color 0.2s, box-shadow 0.2s;
        }

        #todo-form button:hover {
            background-color: var(--color-blue-hover); /* hover:bg-blue-700 */
        }

        #todo-form button:focus {
            /* focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 */
            outline: none;
            box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5); /* ring-2 ring-blue-500 ring-opacity-50 */
        }

        /* 3. 过滤按钮 */
        #filter-buttons {
            /* flex justify-center gap-2 mb-4 */
            display: flex;
            justify-content: center;
            gap: 0.5rem; /* gap-2 */
            margin-bottom: 1rem; /* mb-4 */
        }

        .filter-btn {
            /* py-2 px-4 rounded-lg text-sm font-medium bg-gray-700 hover:bg-gray-600 transition */
            padding: 0.5rem 1rem; /* py-2 px-4 */
            border-radius: 0.5rem; /* rounded-lg */
            font-size: 0.875rem; /* text-sm */
            font-weight: 500; /* font-medium */
            background-color: var(--color-bg-input);
            color: var(--color-text);
            border: none;
            cursor: pointer;
            transition: background-color 0.2s, color 0.2s;
        }

        .filter-btn:hover {
            background-color: #4b5563; /* hover:bg-gray-600 */
        }

        /* 过滤按钮激活状态 */
        .filter-btn.active {
            background-color: var(--color-blue); /* bg-blue-600 */
            color: #ffffff;
        }

        /* 4. 待办事项列表 */
        #todo-list {
            /* space-y-2 */
            display: flex;
            flex-direction: column;
            gap: 0.5rem; /* space-y-2 (用 gap 替代) */
            list-style: none;
        }

        /* 列表为空时的占位符 */
        .empty-list-placeholder {
            /* text-center text-gray-500 py-4 */
            text-align: center;
            color: var(--color-text-dim);
            padding: 1rem 0; /* py-4 */
        }
        
        /* 5. 待办事项 */
        .todo-item {
            /* flex items-center p-3 bg-gray-700 rounded-lg shadow-md */
            display: flex;
            align-items: center;
            padding: 0.75rem; /* p-3 */
            background-color: var(--color-bg-input);
            border-radius: 0.5rem; /* rounded-lg */
            box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-md */
            transition: all 0.3s ease;
        }

        .todo-item span {
            /* flex-grow text-gray-100 break-all */
            flex-grow: 1;
            color: var(--color-text);
            word-break: break-all; /* break-all */
            transition: color 0.3s;
        }

        /* 事项完成时的样式 */
        .todo-item.completed span {
            text-decoration: line-through;
            color: var(--color-text-light); /* text-gray-400 */
        }

        /* 6. 自定义 Checkbox */
        .custom-checkbox {
            appearance: none;
            -webkit-appearance: none;
            height: 20px;
            width: 20px;
            min-width: 20px; /* flex-shrink-0 */
            flex-shrink: 0; /* flex-shrink-0 */
            background-color: #4b5563;
            border: 2px solid #6b7280;
            border-radius: 6px;
            display: inline-block;
            position: relative;
            cursor: pointer;
            transition: all 0.2s ease;
            margin-right: 0.75rem; /* mr-3 */
        }

        .custom-checkbox:checked {
            background-color: var(--color-blue);
            border-color: var(--color-blue-dark);
        }

        .custom-checkbox:checked::after {
            content: "";
            position: absolute;
            left: 6px;
            top: 2px;
            width: 6px;
            height: 12px;
            border: solid white;
            border-width: 0 3px 3px 0;
            transform: rotate(45deg);
        }

        /* 7. 删除按钮 */
        .delete-btn {
            /* text-gray-500 hover:text-red-500 transition ml-2 p-1 flex-shrink-0 */
            color: var(--color-text-dim);
            background: none;
            border: none;
            cursor: pointer;
            transition: color 0.2s;
            margin-left: 0.5rem; /* ml-2 */
            padding: 0.25rem; /* p-1 */
            flex-shrink: 0;
            display: flex; /* 用于居中 svg */
            align-items: center;
            justify-content: center;
        }

        .delete-btn:hover {
            color: var(--color-red-hover); /* hover:text-red-500 */
        }

        .delete-btn svg {
            /* pointer-events-none */
            pointer-events: none;
        }


        /* 8. 动画效果*/
        
        /* 添加事项时的淡入和上移动画 */
        @keyframes fadeInDown {
            from {
                opacity: 0;
                transform: translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* 删除事项时的淡出、缩小和高度折叠动画 */
        .todo-item.fade-out {
            animation: fadeOutShrink 0.3s ease-out forwards;
        }

        @keyframes fadeOutShrink {
            from {
                opacity: 1;
                transform: scale(1);
                max-height: 100px;
                /* 对应 gap: 0.5rem */
                margin-top: 0.5rem; 
                padding-top: 0.75rem; 
                padding-bottom: 0.75rem;
            }
            to {
                opacity: 0;
                transform: scale(0.95);
                max-height: 0;
                margin-top: 0;
                padding-top: 0;
                padding-bottom: 0;
                overflow: hidden;
            }
        }
        
        /* 应用添加入场动画 */
        .todo-item-enter {
            animation: fadeInDown 0.3s ease-out;
        }

        /* 9. 统计样式*/
        .todo-stats {
            /* text-center text-sm text-gray-500 mt-4 */
            text-align: center;
            font-size: 0.875rem; /* text-sm */
            color: var(--color-text-dim);
            margin-top: 1rem; /* mt-4 */
            padding-top: 1rem; /* pt-4 */
            border-top: 1px solid var(--color-border); /* border-t */
        }

    </style>
</head>
<body>
    <div class="app-container">
        
        <h1 class="app-title">我的待办事项</h1>

        <form id="todo-form">
            <input 
                type="text" 
                id="todo-input"
                placeholder="添加一个新任务..."
                autocomplete="off"
            >
            <button type="submit">
                添加
            </button>
        </form>

        <div id="filter-buttons">
            <button class="filter-btn active" data-filter="all">全部</button>
            <button class="filter-btn" data-filter="active">未完成</button>
            <button class="filter-btn" data-filter="completed">已完成</button>
        </div>

        <ul id="todo-list">
            <!-- 待办事项将通过 JS 动态插入到这里 -->
        </ul>

        <!-- 统计信息 -->
        <div id="todo-stats" class="todo-stats">
            <!-- 统计信息将通过 JS 动态插入 -->
        </div>

    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {

            /**
             * (1) 待办事项类 (TodoItem Class)
             */
            class TodoItem {
                constructor(text) {
                    this.id = `todo-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
                    this.text = text;
                    this.completed = false;
                    this.createdAt = new Date();
                }
            }

            /**
             * 主应用类
             */
            class TodoListApp {
                constructor() {
                    this.todoForm = document.getElementById('todo-form');
                    this.todoInput = document.getElementById('todo-input');
                    this.todoList = document.getElementById('todo-list');
                    this.filterButtonsContainer = document.getElementById('filter-buttons');
                    this.todoStats = document.getElementById('todo-stats');
                    
                    this.todos = [];
                    this.currentFilter = 'all';
                    this.localStorageKey = 'vanillaJsTodos';
                }

                init() {
                    this.loadTodos();
                    this.bindEvents();
                    this.render();
                    this.updateStats();
                }

                bindEvents() {
                    this.todoForm.addEventListener('submit', (e) => {
                        e.preventDefault();
                        const text = this.todoInput.value.trim();
                        if (text) {
                            this.addTodo(text);
                            this.todoInput.value = '';
                        }
                    });

                    this.todoList.addEventListener('click', (e) => {
                        const target = e.target;
                        const todoItemElement = target.closest('.todo-item');
                        if (!todoItemElement) return;

                        const id = todoItemElement.dataset.id;

                        if (target.closest('.delete-btn')) {
                            this.deleteTodo(id);
                        } 
                        else if (target.classList.contains('custom-checkbox')) {
                            this.toggleComplete(id);
                        }
                    });

                    this.filterButtonsContainer.addEventListener('click', (e) => {
                        const target = e.target.closest('.filter-btn');
                        if (target) {
                            const filter = target.dataset.filter;
                            this.setFilter(filter);
                        }
                    });
                }

                addTodo(text) {
                    const newTodo = new TodoItem(text);
                    this.todos.unshift(newTodo);
                    this.saveTodos();
                    this.render(true); // 传入 true 表示是新添加的
                    this.updateStats();
                }

                toggleComplete(id) {
                    const todo = this.todos.find(t => t.id === id);
                    if (todo) {
                        todo.completed = !todo.completed;
                        this.saveTodos();
                        
                        //只更新 DOM，而不是完全重新渲染
                        const todoElement = this.todoList.querySelector(`[data-id="${id}"]`);
                        if(todoElement) {
                            todoElement.classList.toggle('completed');
                        }
                        
                        // 如果在 'active' 或 'completed' 视图，则需要重新渲染
                        if (this.currentFilter !== 'all') {
                            this.render();
                        }
                    }
                    this.updateStats();
                }

                deleteTodo(id) {
                    const todoElement = this.todoList.querySelector(`[data-id="${id}"]`);
                    
                    if (todoElement) {
                        todoElement.classList.add('fade-out');
                        
                        todoElement.addEventListener('animationend', () => {
                            this.todos = this.todos.filter(t => t.id !== id);
                            this.saveTodos();
                            todoElement.remove();
                            this.updateStats();
                            // 检查是否列表变空
                            if (this.getFilteredTodos().length === 0) {
                                this.renderEmptyState();
                            }
                        }, { once: true });
                    }
                }

                setFilter(filter) {
                    this.currentFilter = filter;
                    this.updateFilterButtons();
                    this.render();
                }

                updateFilterButtons() {
                    document.querySelectorAll('.filter-btn').forEach(btn => {
                        if (btn.dataset.filter === this.currentFilter) {
                            btn.classList.add('active');
                        } else {
                            btn.classList.remove('active');
                        }
                    });
                }

                getFilteredTodos() {
                    switch (this.currentFilter) {
                        case 'active':
                            return this.todos.filter(t => !t.completed);
                        case 'completed':
                            return this.todos.filter(t => t.completed);
                        case 'all':
                        default:
                            return this.todos;
                    }
                }

                saveTodos() {
                    localStorage.setItem(this.localStorageKey, JSON.stringify(this.todos));
                }

                loadTodos() {
                    const todosString = localStorage.getItem(this.localStorageKey);
                    this.todos = todosString ? JSON.parse(todosString) : [];
                }

                /**
                 * 更新统计信息
                 */
                updateStats() {
                    const totalTasks = this.todos.length;
                    const completedTasks = this.todos.filter(t => t.completed).length;

                    if (totalTasks === 0) {
                        this.todoStats.innerHTML = '添加你的第一个任务吧！';
                    } else {
                        this.todoStats.innerHTML = `
                            总共 ${totalTasks} 个任务
                            <span style="margin: 0 0.5rem;">|</span>
                            ${completedTasks} 个已完成
                        `;
                    }
                }

                /**
                 * 渲染空状态
                 */
                renderEmptyState() {
                    this.todoList.innerHTML = `
                        <li class="empty-list-placeholder">
                            这里还没有任务...
                        </li>
                    `;
                }

                render(isNewItem = false) {
                    const filteredTodos = this.getFilteredTodos();
                    
                    // 仅在新添加时才部分渲染
                    if (isNewItem) {
                        // 如果列表之前是空的，先清空 "空状态"
                        if (this.todoList.querySelector('.empty-list-placeholder')) {
                            this.todoList.innerHTML = '';
                        }
                        
                        const newTodo = filteredTodos[0];
                        if (this.currentFilter === 'all' || (this.currentFilter === 'active' && !newTodo.completed)) {
                           const newElement = this.createTodoElement(newTodo);
                           newElement.classList.add('todo-item-enter');
                           this.todoList.prepend(newElement);
                        }
                    } else {
                        // 完整渲染
                        if (filteredTodos.length === 0) {
                            this.renderEmptyState();
                            return;
                        }
                        
                        this.todoList.innerHTML = ''; // 清空
                        filteredTodos.forEach(todo => {
                            const todoElement = this.createTodoElement(todo);
                            this.todoList.appendChild(todoElement);
                        });
                    }
                    
                    this.updateFilterButtons();
                }

                createTodoElement(todo) {
                    const li = document.createElement('li');
                    li.dataset.id = todo.id;
                    // 使用 CSS class
                    li.className = 'todo-item';

                    if (todo.completed) {
                        li.classList.add('completed');
                    }

                    li.innerHTML = `
                        <input 
                            type="checkbox" 
                            class="custom-checkbox" 
                            ${todo.completed ? 'checked' : ''}
                        >
                        <span>${this.escapeHTML(todo.text)}</span>
                        <button class="delete-btn">
                            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <polyline points="3 6 5 6 21 6"></polyline>
                                <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                                <line x1="10" y1="11" x2="10" y2="17"></line>
                                <line x1="14" y1="11" x2="14" y2="17"></line>
                            </svg>
                        </button>
                    `;
                    return li;
                }

                escapeHTML(str) {
                    return str.replace(/[&<>"']/g, function(match) {
                        return {
                        '&': '&amp;',
                        '<': '&lt;',
                        '>': '&gt;',
                        '"': '&quot;',
                        "'": '&#39;'
                        }[match];
                    });
                }
            }

            // 启动应用
            const app = new TodoListApp();
            app.init();

        });
    </script>

</body>
</html>